package com.bfly.mall.wechat.mp.service.message;

import com.alibaba.fastjson.JSONObject;
import com.bfly.common.json.JaxbUtil;
import com.bfly.mall.user.entity.User;
import com.bfly.mall.user.service.IUserService;
import com.bfly.mall.wechat.entity.WeChatMp;
import com.bfly.mall.wechat.mp.dto.WeChatMpUserInfo;
import com.bfly.mall.wechat.mp.dto.WeChatMpUserInfoRequest;
import com.bfly.mall.wechat.mp.service.WeChatMPAPi;
import com.bfly.mall.wechat.mp.service.message.event.PushEventMsgHandler;
import com.bfly.mall.wechat.mp.service.message.receive.ReceiveMsgHandler;
import com.bfly.mall.wechat.service.IWeChatMpService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.Arrays;
import java.util.List;

/**
 * 微信消息处理类<br/>解析不同类型的微信消息
 *
 * @author 长沙商脉科技有限公司
 * @date 2021/1/7 19:22
 */
@Component
public class WeChatMpMsgFactory {

    // 事件推送消息类型
    public static final String MSG_TYPE_PUSH_EVENT = "event";            //事件推送消息类型

    // 以下为普通微信用户向公众账号发消息时的消息类型
    public static final String MSG_TYPE_RECEIVE_TEXT = "text";              //文本消息类型
    public static final String MSG_TYPE_RECEIVE_IMAGE = "image";            //图片消息
    public static final String MSG_TYPE_RECEIVE_VOICE = "voice";            //语音消息
    public static final String MSG_TYPE_RECEIVE_VIDEO = "video";            //视频消息
    public static final String MSG_TYPE_RECEIVE_SHORT_VIDEO = "shortvideo"; //小视频消息
    public static final String MSG_TYPE_RECEIVE_LOCATION = "location";      //地理位置消息
    public static final String MSG_TYPE_RECEIVE_LINK = "link";              //连接消息

    private static Logger logger = LoggerFactory.getLogger(WeChatMpMsgFactory.class);

    private static PushEventMsgHandler pushEventMsgHandler;
    private static ReceiveMsgHandler receiveMsgHandler;

    private static IWeChatMpService weChatMpService;
    private static IUserService userService;

    @Autowired
    public void setPushEventMsgHandler(PushEventMsgHandler pushEventMsgHandler) {
        WeChatMpMsgFactory.pushEventMsgHandler = pushEventMsgHandler;
    }

    @Autowired
    public void setReceiveMsgHandler(ReceiveMsgHandler receiveMsgHandler) {
        WeChatMpMsgFactory.receiveMsgHandler = receiveMsgHandler;
    }

    @Autowired
    public void setWeChatMpService(IWeChatMpService weChatMpService) {
        this.weChatMpService = weChatMpService;
    }
    @Autowired
    public void setUserService(IUserService userService) {
        this.userService = userService;
    }

    /**
     * 通过公众号的微信号或原始ID查找对应的公众号信息
     *
     * @author 长沙商脉科技有限公司
     * @date 2021/1/7 22:55
     */
    private static WeChatMp getMp(String originId) {
        WeChatMp mp = weChatMpService.getWeChatMpByOriginId(originId);
        return mp;
    }

    /**
     * 查找用户信息
     *
     * @author 长沙商脉科技有限公司
     * @date 2021/1/7 23:04
     */
    private static User getUser(WeChatMp mp, String openId) {
        User user = userService.getUser(openId);
        if (user == null) {
            // 不存在的用户则新增
            List<WeChatMpUserInfoRequest> list = Arrays.asList(new WeChatMpUserInfoRequest(openId));
            List<WeChatMpUserInfo> mpUserInfos = WeChatMPAPi.getMpUserInfo(mp.getAppId(), mp.getAppSecret(), list);
            userService.merge(mp.getId(), mpUserInfos.get(0));
            user = userService.getUser(openId);
        }
        return user;
    }

    /**
     * 处理微信消息
     *
     * @author 长沙商脉科技有限公司
     * @date 2021/1/7 19:23
     */
    public static String execute(String xml) {
        logger.info("接收到微信服务器推送消息:" + xml);
        JSONObject json = JaxbUtil.xmlToJson(xml);
        json = json.getJSONObject("xml");
        logger.info(json.toJSONString());
        String msgType = json.getString("MsgType");
        String openId = json.getString("FromUserName");     // 用户openId
        String weChatMpId = json.getString("ToUserName");   // 公众号的微信号或原始ID
        WeChatMp mp = getMp(weChatMpId);
        User user = getUser(mp, openId);
        String result = "";
        switch (msgType) {
            case MSG_TYPE_PUSH_EVENT:
                result = pushEventMsgHandler.handle(mp,user,json);
                break;
            case MSG_TYPE_RECEIVE_TEXT:
            case MSG_TYPE_RECEIVE_IMAGE:
            case MSG_TYPE_RECEIVE_VOICE:
            case MSG_TYPE_RECEIVE_VIDEO:
            case MSG_TYPE_RECEIVE_SHORT_VIDEO:
            case MSG_TYPE_RECEIVE_LOCATION:
            case MSG_TYPE_RECEIVE_LINK:
                receiveMsgHandler.handle(json);
                break;
            default:
                break;
        }
        return result;
    }
}
